/**
 * @author Alexis Brunet
 */
#ifndef RECURSIVEDESCENTPARSER_H_
#define RECURSIVEDESCENTPARSER_H_

#define DEBUG_PARSER 0	// should be in Definitions.h

#include "Token.h"
#include "Observer.h" // for ScannerInterface
#include "TableManager.h"
#include "FunctionEntry.h"
#include "IntermediateCode.h"
#include "LiteralTable.h"
#include "MoonGenerator.h"

class RecursiveDescentParser : public ParserInterface
{
public:
	RecursiveDescentParser(ScannerInterface* si/* ,TargetCodeGenerator* tcg */);
	virtual ~RecursiveDescentParser();
	
	void start();
	bool getError();
	
	void registerObserver(ErrorObserver* o);
	void removeObserver(ErrorObserver* o);
	
private:
	TargetCodeGenerator* codeGenerator;
	ScannerInterface* scanner; // A pointer to the scanner	
	Token token; // the current token being evaluated
	
	bool errorCondition; // indicates if an error occured
	int errorCount;
	std::string mainLabel;
	std::string currentReturnLabel;
	
	TableManager symTab; // global symbol table
	LiteralTable litTab;
	IntermediateCode iCode;
		
	std::vector<ErrorObserver*> errorObservers;
	
	
	void notifyErrorObservers(std::string errorMsg);
	
	// check if member token is of type tkType
	void match(TokenType tkType);
	void matchParameters(FunctionEntry* fEntry, ParamList* &callerParams, Token tk);
	
	// error handlers
	void errorHandler();
	void errorHandler(std::string errorMessage, Token tk, bool recoverable=true);
	void errorHandler(std::string errorMessage, int lineNumber, bool recoverable=true);
	
	// functions representing the productions of the grammar
	void prg();
	void functions();
	void functions_prime();
	void funct_def();
	Token f_name();
	void par_list();
	void par_list_prime();
	ParamList* par_dec_list();
	ParamList* par_dec_list_prime(Type t);
	VariableEntry* par_spec(Type t);
	VariableAttribute par_spec_prime();
	Type f_type();
	Type type();
	void st();
	void st_prime(Type type);
	void st_factor_ident(TableEntry* te=NULL);
	void st_factor_type(VariableEntry* &ve);
	void st_factor_num(VariableEntry* &ve);
	void st_factor_right_bracket(Type t);
	void st_factor_final(Type t);
	void comp_st(bool createSymbolTable=true);
	void st_list();
	void st_list_prime();
	void asg_st();
	Type type_a();
	VariableAttribute arr_spec();
	VariableEntry* var();
	attr var_prime(VariableEntry* entry);
	attr log_exp();
	attr log_exp_prime(attr lhs);
	attr log_term();
	attr log_term_prime(attr lhs);
	attr log_prim();
	attr log_prim_prime();
	OpCode rel_op();
	attr exp();
	attr exp_prime(attr pAttr);
	attr term();
	attr term_prime(attr pAttr);
	attr prim();
	attr prim_prime(TableEntry* pTabEntr=NULL);
	OpCode add_op();
	OpCode mult_op();
	ParamList* i_list();
	ParamList* i_list_prime();
	ParamList* o_list();
	void o_list_prime(ParamList* &pList);
	attr oelem(ParamList* &pList);
};

#endif /*RECURSIVEDESCENTPARSER_H_*/
